/*
 *  Copyright 2010 INFN - APE group
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

//#define CUQU_DISABLE_CUPRINTF 1
//#define CUOS_ENABLE_TRACING 1

#include <cuos/utils.h>
#include <cuos/types.h>
#include <cuos/runtime.h>
#include <cuos/detail/handler.h>

using namespace cuos::system_service;

//----------------------------------------------------------------------

cuos::host::handler::handler(sys_req_t *req)
{
    cuosTrace("CTOR handler this=%p req=%p\n", this, req);
    assert(req);
    m_req = *req;
}

//----------------------------------------------------------------------

static inline double delta_t(timeval &t1, timeval &t2)
{
    return (double)(t2.tv_sec - t1.tv_sec) + (double)(t2.tv_usec - t1.tv_usec)/1000000.0;
}

cuos::host::handler::~handler()
{ 
    cuosTrace("DTOR handler this=%p\n", this);
    double i2r = delta_t(m_init_tm, m_reply_tm);
    double r2d = delta_t(m_reply_tm, m_done_tm);
    cuosTrace("times: init={%d:%ld} init->reply=%fs reply->done=%fs\n",
              m_init_tm.tv_sec, m_init_tm.tv_usec,
              i2r, r2d);
}

//----------------------------------------------------------------------

cuos::host::handler *cuos::host::make_handler(sys_req_t *req)
{
    handler *h = 0;
    assert(req);
    cuosTrace("create_task sys_id=%d\n", req->id);
    switch(req->id) {
    case sys_null:
        break;
    case sys_open:
        break;
    case sys_close:
        break;
    case sys_write:
        break;
    case sys_read:
        break;
    case sys_mpi_send:
    case sys_mpi_isend:
    case sys_mpi_bsend:
        h = make_mpi_send_handler(req);
        break;
    case sys_mpi_recv:
    case sys_mpi_irecv:
        h = make_mpi_recv_handler(req);
        break;
    case sys_mpi_test:
        break;
    case sys_mpi_wait:
        break;
    default:
        break;
    }
    cuosTrace("created handler=%p\n", h);
    return h;
}

//----------------------------------------------------------------------

#if 0
int cuos::host::handler::progress(runtime *rtm)
{
    int ret = SUCCESS;
    int retcode;
    switch(state()) {
    case NONE:
        cuosError("state=NONE should never happen!\n");
        ret = RUNTIME;
        break;
    case FREE:
        cuosTrace("state=FREE\n");
        break;
    case INIT:
        cuosTrace("state=INIT\n");
        retcode = init(rtm);
        if(retcode == SUCCESS) {
            m_state = PROCESSING;
        } else if(retcode == WOULDBLOCK) {
            // keep on going
        } else {
            // some other error
            m_state = ERROR;
            ret = retcode;
        }
        break;
    case PROCESSING:
        cuosTrace("state=PROCESSING\n");
        retcode = process(rtm);
        if(retcode == SUCCESS) {

        } else if(retcode == WOULDBLOCK) {
            // keep on going
        } else {
            // some other error
            m_state = DONE;
            ret = retcode;
        }
        break;
    case REPLYING:
        cuosTrace("state=REPLYING\n");
        {
            m_rep.serial = m_req.serial;
            m_rep.flags = 0;
            // m_rep.retcode <<<----
            cuosTrace("this system service needs a reply, sending it back\n");
            retcode = rtm->push_reply(&m_rep); // m_queue_h2d.timed_push(&i->m_rep, timeout_infinite);
            if(cuqu::SUCCESS == retcode) {
                // fine!
                m_state = DONE;
            } else if(cuqu::WOULDBLOCK == retcode) {
                // something is wrong !!!
                cuosError("got WOULDBLOCK while sending reply back\n");
                ret = RUNTIME;
            } else {
                //cuqu::INVALID:
                //cuqu::UNSET:
                cuosError("got retcode=%d while sending reply back\n", retcode);
                ret = INVALID;
            }
        }
        break;
    case DONE:
        cuosTrace("state=DONE\n");
        // stay here until runtime does:
        // remove it from queue
        // delete it
        break;
    case ERROR:
        cuosTrace("state=ERROR\n");
        break;
    default:
        cuosError("state=default should never happen!\n");
        ret = RUNTIME;
        break;
    }
    return ret;
}
#endif

//----------------------------------------------------------------------

/*
 * Local variables:
 *  mode: c++
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  tab-width: 4
 *  indent-tabs-mode: nil
 * End:
 */
